package cn.ddiancan.xddcloud.ddccore.exception;

import java.util.Objects;

import cn.ddiancan.xddcloud.common.entity.CommonResult;
import cn.ddiancan.xddcloud.common.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;

@Component
@ControllerAdvice(annotations = RestController.class)
@Slf4j
public class GlobalExceptionHalder {

    @ExceptionHandler(IllegalArgumentException.class)
    public ModelAndView handleIllegalException(IllegalArgumentException e) {
        log.error("系统异常,被全局捕获:{}",e.getMessage(), e);
        ModelAndView modelAndView = new ModelAndView(IllegalArgumentException.class.getName());
        CommonResult<IllegalArgumentException> commonResult = new CommonResult<>();
        commonResult.setMsg(e.getMessage());
        commonResult.setCode(HttpStatus.BAD_REQUEST.value());
        modelAndView.setStatus(HttpStatus.BAD_REQUEST);
        modelAndView.addObject(commonResult);
        View view = (model, request, response) -> {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(commonResult));
        };
        modelAndView.setView(view);
        return modelAndView;
    }

    @ExceptionHandler(ServiceException.class)
    public ModelAndView handleServiceException(ServiceException exception) {
        log.error("系统异常,被全局捕获:{}",exception.getRuntimeExceptionMessage(), exception);
        ModelAndView modelAndView = new ModelAndView(IllegalArgumentException.class.getName());
        CommonResult<ServiceException> commonResult = new CommonResult<>();
        commonResult.setMsg(exception.getRuntimeExceptionMessage());
        commonResult.setCode(exception.getRuntimeExceptionCode());
        modelAndView.setStatus(HttpStatus.OK);
        modelAndView.addObject(commonResult);
        View view = (model, request, response) -> {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(commonResult));
        };
        modelAndView.setView(view);
        return modelAndView;
    }

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception exception) {
        log.error("系统异常,被全局捕获:{}", exception.getMessage(), exception);
        ModelAndView modelAndView = new ModelAndView(IllegalArgumentException.class.getName());
        CommonResult<Exception> commonResult = new CommonResult<>();
        commonResult.setMsg(exception.getMessage());
        commonResult.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
        modelAndView.setStatus(HttpStatusCode.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()));
        modelAndView.addObject(commonResult);
        View view = (model, request, response) -> {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(commonResult));
        };
        modelAndView.setView(view);
        return modelAndView;
    }

    // 参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<CommonResult<ServiceException>> handleValidationExceptions(
        MethodArgumentNotValidException ex) {
        log.error("参数校验异常,被全局捕获:{}", ex.getMessage(), ex);
        // 获取第一个字段错误信息
        FieldError fieldError = ex.getBindingResult().getFieldError();
        ObjectError globalError = ex.getBindingResult().getGlobalError();
        CommonResult<ServiceException> commonResult = new CommonResult<>();
        // 如果有字段错误，使用字段错误消息
        if (fieldError != null) {
            commonResult.setMsg(fieldError.getDefaultMessage());
        } else {
            // 如果没有字段错误，返回默认的错误信息
            commonResult.setMsg(Objects.nonNull(globalError) ? globalError.getDefaultMessage() : "参数校验异常");
        }
        // 设置统一的错误码
        commonResult.setCode(330);
        // 返回 400 状态码，表示客户端请求错误
        return new ResponseEntity<>(commonResult, HttpStatus.OK);
    }
}
